package com.zhentao.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhentao.dto.EffectiveParamQueryDTO;
import com.zhentao.dto.ParamValueDTO;
import com.zhentao.dto.ParamValueQueryDTO;
import com.zhentao.mapper.ParamDefinitionMapper;
import com.zhentao.mapper.ParamValueMapper;
import com.zhentao.pojo.ParamDefinition;
import com.zhentao.pojo.ParamValue;
import com.zhentao.service.ParamValueService;
import com.zhentao.vo.EffectiveParamVO;
import com.zhentao.vo.ParamValueVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author hp
* @description 针对表【param_value(参数值表：存储参数的实际值，支持多版本和多作用域)】的数据库操作Service实现
* @createDate 2025-08-28 08:36:25
*/
@Service
public class ParamValueServiceImpl extends ServiceImpl<ParamValueMapper, ParamValue>
    implements ParamValueService{

    @Autowired
    private ParamDefinitionMapper paramDefinitionMapper;

    /**
     * 作用域优先级映射（数值越大优先级越高）
     */
    private static final Map<String, Integer> SCOPE_PRIORITY = new HashMap<>();
    static {
        SCOPE_PRIORITY.put("USER", 4);        // 用户级优先级最高
        SCOPE_PRIORITY.put("ENTERPRISE", 3);  // 企业级
        SCOPE_PRIORITY.put("CUSTOMS_CODE", 2); // 关区级
        SCOPE_PRIORITY.put("GLOBAL", 1);      // 全局级优先级最低
    }

    @Override
    public EffectiveParamVO getEffectiveParamValue(EffectiveParamQueryDTO queryDTO) {
        // 1. 根据参数键查找参数定义
        ParamDefinition paramDefinition = getParamDefinitionByKey(queryDTO.getParamKey());
        if (paramDefinition == null) {
            throw new RuntimeException("参数定义不存在：" + queryDTO.getParamKey());
        }

        // 2. 确定查询时间
        Date queryTime = parseQueryTime(queryDTO.getQueryTime());

        // 3. 按优先级查询生效的参数值
        List<String> scopeTypes = Arrays.asList("USER", "ENTERPRISE", "CUSTOMS_CODE", "GLOBAL");
        
        for (String scopeType : scopeTypes) {
            String scopeValue = getScopeValue(scopeType, queryDTO);
            ParamValue effectiveValue = findEffectiveParamValue(
                paramDefinition.getId(), scopeType, scopeValue, queryTime
            );
            
            if (effectiveValue != null) {
                return convertToEffectiveParamVO(paramDefinition, effectiveValue, queryTime);
            }
        }

        // 4. 如果没有找到任何生效值，返回默认值
        if (StringUtils.hasText(paramDefinition.getDefaultValue())) {
            return createDefaultEffectiveParamVO(paramDefinition, queryTime);
        }

        throw new RuntimeException("未找到生效的参数值：" + queryDTO.getParamKey());
    }

    @Override
    public Map<String, EffectiveParamVO> getBatchEffectiveParams(List<String> paramKeys, String scopeType, String scopeValue) {
        Map<String, EffectiveParamVO> result = new HashMap<>();
        
        for (String paramKey : paramKeys) {
            try {
                EffectiveParamQueryDTO queryDTO = new EffectiveParamQueryDTO();
                queryDTO.setParamKey(paramKey);
                queryDTO.setScopeType(scopeType);
                queryDTO.setScopeValue(scopeValue);
                
                EffectiveParamVO paramVO = getEffectiveParamValue(queryDTO);
                result.put(paramKey, paramVO);
            } catch (Exception e) {
                // 忽略单个参数的错误
                System.out.println("批量获取参数失败: " + paramKey + " - " + e.getMessage());
            }
        }
        
        return result;
    }

    @Override
    public Page<ParamValueVO> queryParamValues(ParamValueQueryDTO queryDTO) {
        // 构建查询条件
        LambdaQueryWrapper<ParamValue> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(queryDTO.getParamId() != null, ParamValue::getParamId, queryDTO.getParamId())
                   .eq(StringUtils.hasText(queryDTO.getScopeType()), ParamValue::getScopeType, queryDTO.getScopeType())
                   .eq(StringUtils.hasText(queryDTO.getScopeValue()), ParamValue::getScopeValue, queryDTO.getScopeValue())
                   .eq(queryDTO.getIsActive() != null, ParamValue::getStatus, queryDTO.getIsActive())
                   .orderByDesc(ParamValue::getCreateTime);

        // 分页查询
        Page<ParamValue> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
        Page<ParamValue> resultPage = this.page(page, queryWrapper);

        // 转换为VO
        Page<ParamValueVO> voPage = new Page<>();
        BeanUtils.copyProperties(resultPage, voPage);
        
        List<ParamValueVO> voList = resultPage.getRecords().stream()
                .map(this::convertToParamValueVO)
                .collect(Collectors.toList());
        voPage.setRecords(voList);

        return voPage;
    }

    @Override
    public ParamValueVO getParamValueDetail(Long id) {
        ParamValue paramValue = this.getById(id);
        if (paramValue == null) {
            return null;
        }
        return convertToParamValueVO(paramValue);
    }

    @Override
    public boolean createParamValue(ParamValueDTO dto) {
        ParamValue paramValue = new ParamValue();
        BeanUtils.copyProperties(dto, paramValue);
        paramValue.setCreateTime(new Date());
        paramValue.setCreateBy("system");
        return this.save(paramValue);
    }

    @Override
    public boolean updateParamValue(Long id, ParamValueDTO dto) {
        ParamValue existValue = this.getById(id);
        if (existValue == null) {
            throw new RuntimeException("参数值不存在");
        }

        BeanUtils.copyProperties(dto, existValue);
        // 注意：ParamValue 实体没有 updateTime 和 updateBy 字段
        // existValue.setUpdateTime(new Date());
        // existValue.setUpdateBy("system");
        return this.updateById(existValue);
    }

    @Override
    public boolean deleteParamValue(Long id) {
        return this.removeById(id);
    }

    @Override
    public List<ParamValueVO> getParamValueHistory(Long paramId) {
        LambdaQueryWrapper<ParamValue> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ParamValue::getParamId, paramId)
                   .orderByDesc(ParamValue::getCreateTime);
        
        List<ParamValue> historyList = this.list(queryWrapper);
        return historyList.stream()
                .map(this::convertToParamValueVO)
                .collect(Collectors.toList());
    }

    @Override
    public boolean toggleParamValueStatus(Long id, Integer isActive) {
        ParamValue paramValue = this.getById(id);
        if (paramValue == null) {
            throw new RuntimeException("参数值不存在");
        }
        
        paramValue.setStatus(isActive);
        // 注意：ParamValue 实体没有 updateTime 字段
        return this.updateById(paramValue);
    }

    @Override
    public boolean hasConflictParamValue(Long paramId, String scopeType, String scopeValue, 
                                       Date effectiveTime, Date expireTime, Long excludeId) {
        // 简化实现，实际项目中需要详细的时间范围冲突检查
        return false;
    }

    // ===== 私有辅助方法 =====

    private ParamDefinition getParamDefinitionByKey(String paramKey) {
        LambdaQueryWrapper<ParamDefinition> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ParamDefinition::getParamKey, paramKey);
        return paramDefinitionMapper.selectOne(queryWrapper);
    }

    private Date parseQueryTime(String queryTimeStr) {
        if (!StringUtils.hasText(queryTimeStr)) {
            return new Date();
        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return sdf.parse(queryTimeStr);
        } catch (Exception e) {
            return new Date();
        }
    }

    private String getScopeValue(String scopeType, EffectiveParamQueryDTO queryDTO) {
        if ("GLOBAL".equals(scopeType)) {
            return null;
        }
        return queryDTO.getScopeValue();
    }

    private ParamValue findEffectiveParamValue(Long paramId, String scopeType, String scopeValue, Date queryTime) {
        LambdaQueryWrapper<ParamValue> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ParamValue::getParamId, paramId)
                   .eq(ParamValue::getScopeType, scopeType)
                   .eq(scopeValue != null, ParamValue::getScopeValue, scopeValue)
                   .eq(ParamValue::getStatus, 1)
                   .le(ParamValue::getEffectiveTime, queryTime)
                   .and(wrapper -> wrapper.isNull(ParamValue::getExpireTime)
                                         .or()
                                         .ge(ParamValue::getExpireTime, queryTime))
                   .orderByDesc(ParamValue::getPriority)
                   .orderByDesc(ParamValue::getCreateTime)
                   .last("LIMIT 1");
        
        return this.getOne(queryWrapper);
    }

    private EffectiveParamVO convertToEffectiveParamVO(ParamDefinition definition, ParamValue value, Date queryTime) {
        EffectiveParamVO vo = new EffectiveParamVO();
        vo.setParamKey(definition.getParamKey());
        vo.setParamName(definition.getParamName());
        vo.setDataType(definition.getDataType() != null ? definition.getDataType().toString() : "");
        vo.setParamValue(value.getParamValue());
        vo.setScopeType(value.getScopeType() != null ? value.getScopeType().toString() : "");
        vo.setScopeValue(value.getScopeValue());
        vo.setQueryTime(queryTime);
        vo.setSource((value.getScopeType() != null ? value.getScopeType().toString() : "") + "级参数");
        return vo;
    }

    private EffectiveParamVO createDefaultEffectiveParamVO(ParamDefinition definition, Date queryTime) {
        EffectiveParamVO vo = new EffectiveParamVO();
        vo.setParamKey(definition.getParamKey());
        vo.setParamName(definition.getParamName());
        vo.setDataType(definition.getDataType() != null ? definition.getDataType().toString() : "");
        vo.setParamValue(definition.getDefaultValue());
        vo.setScopeType("DEFAULT");
        vo.setQueryTime(queryTime);
        vo.setSource("默认值");
        return vo;
    }

    private ParamValueVO convertToParamValueVO(ParamValue entity) {
        ParamValueVO vo = new ParamValueVO();
        BeanUtils.copyProperties(entity, vo);
        
        // 获取参数定义信息
        ParamDefinition definition = paramDefinitionMapper.selectById(entity.getParamId());
        if (definition != null) {
            vo.setParamKey(definition.getParamKey());
            vo.setParamName(definition.getParamName());
        }
        
        return vo;
    }
}




